#include "Scheme.h"

namespace Validator
{


using namespace std;

Scheme::Scheme(void)
{
	myClassName = "";
}


Scheme::Scheme(std::string theName,const char *theType)
{
	myClassName = theName;
	strncpy(myType,theType,3);
	myType[3] = '\0'; //nullterminacia
}


Scheme::~Scheme(void)
{}

void Scheme::Add(MetaDirectory theDirectory)
{
	this->myRootDirectories.push_back(theDirectory);;
}

void Scheme::Add(MetaFile  theFile)
{
	this->myRootFiles.push_back(theFile);
}


std::vector<MetaDirectory> &Scheme::GetDirectories()
{
	return myRootDirectories;
}

std::vector<MetaFile> Scheme::GetFiles()
{
	return myRootFiles;
}


bool Scheme::operator==(Scheme theOther)
{
	//najprv porovname subory nachadzajuce sa v roote
	//ak sa nerovna ich pocet nemozu sa schemy rovnat!
	if(this->myRootFiles.size() != theOther.myRootFiles.size() )
		return false;
	
	bool match = false;
	for(unsigned int i=0; i < this->myRootFiles.size(); i++)
	{
		for(unsigned int k=0; k < theOther.myRootFiles.size(); k++)
		{
			if( this->myRootFiles[i].GetName() == theOther.myRootFiles[k].GetName())
			{
				match = true;
				break;
			}
		}

		if(!match)
			return false;
	}

	//porovname adresare 
	//ak sa nerovna ich pocet nemoze sa rovnat schema
	if(this->myRootDirectories.size() != theOther.myRootDirectories.size())
		return false;

	//porovnanie root adresarov, najprv podla nazvu
	match = false;
	int indexI =0, indexK =0;
	for(unsigned int i=0; i < this->myRootDirectories.size() ; i++)
	{
		for(unsigned int k=0; k < theOther.myRootDirectories.size(); k++)
		{
			if(this->myRootDirectories[i].GetName() == theOther.myRootDirectories[k].GetName())
			{
				indexI = i;
				indexK = k;
				match = true;
				break;
			}
		}

		if(!match)
			return false;
		else
		{
			//hlbkove porovnanie dvoch adresarov
			if(!CompareDirectories(this->myRootDirectories[indexI],theOther.myRootDirectories[indexK]))
				return false;
		}
	}

	return true;
}

bool Scheme::operator!=(Scheme &theOne)
{
	return !((*this) == theOne);
}

const std::string& Scheme::GetName() const
{
	return myClassName;
}

std::vector<MetaFile> Scheme::GetFilesToExtract()
{
	if(myFilesToExtract.size() < 1)
	{
		for(std::size_t i=0; i < myRootDirectories.size(); i++)
		{
			get_files(myRootDirectories[i]);
		}
	}

	return myFilesToExtract;
}

//**************************************************************//
//						PRIVATE METHODS							//
//**************************************************************//


bool Scheme::CompareDirectories(MetaDirectory theOne,MetaDirectory theSecond)
{
	//ak jeden z adresarov ma atribut any tak nezalezi na pocte
	//inak kontrolujeme pocet adresarov aj pocet suborov sa ma zhodovat
	if(!theOne.GetAnyFlag() && !theSecond.GetAnyFlag())
	{
		if(theOne.GetDirectories().size() != theSecond.GetDirectories().size())
			return false;
		if(theOne.GetFiles().size() != theSecond.GetFiles().size())
			return false;
		
		bool match = false;
		for(unsigned int i=0; i < theOne.GetFiles().size(); i++)
		{
			for(unsigned int k=0; k < theSecond.GetFiles().size(); k++)
			{
				std::size_t pos1 = theOne.GetFiles()[i].GetName().rfind(theSecond.GetFiles()[k].GetName());
				std::size_t pos2 = theSecond.GetFiles()[k].GetName().rfind(theOne.GetFiles()[i].GetName());

				if( pos1 != std::string::npos || pos2 != std::string::npos )
				{
					match = true;
					break;
				}
			}

			if(!match)
				return false;
		}
	}

	//kontrola adresarov rekurzivne
	bool match = false;
	int indexI =0, indexK =0;
	for(unsigned int i=0; i < theOne.GetDirectories().size() ; i++)
	{
		for(unsigned int k=0; k < theSecond.GetDirectories().size(); k++)
		{
			if(theOne.GetDirectories()[i].GetName() == theSecond.GetDirectories()[k].GetName())
			{
				indexI = i;
				indexK = k;
				match = true;
				break;
			}
		}

		if(!match)
			return false;
		else
		{
			//hlbkove porovnanie dvoch adresarov
			if(!CompareDirectories(theOne.GetDirectories()[indexI],theSecond.GetDirectories()[indexK]))
				return false;
		}
	}
	return true;
}//end of CompareDirectories


void Scheme::get_files(MetaDirectory theDir)
{
	for(std::size_t i=0; i < theDir.GetFiles().size(); i++)
	{
		if(theDir.GetFiles()[i].DoExtract())
		{
			myFilesToExtract.push_back(theDir.GetFiles()[i]);
		}
	}

	for(std::size_t i=0; i < theDir.GetDirectories().size();i++)
	{
		get_files(theDir.GetDirectories()[i]);
	}
}

}//end of namespace